package com.example.admin.controller;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
import com.example.admin.SysUser;
import com.example.admin.entity.GenFieldVo;
import com.example.admin.entity.GenTable;
import com.example.admin.entity.GenTableColumn;
import com.example.admin.entity.GenTableVo;
import com.example.admin.service.IGenTableService;
import com.example.common.config.DbConfig;
import com.example.common.config.GenerConfig;
import com.example.common.generator.Generator;
import com.example.common.generator.entity.GeneratorInfo;
import com.example.shrio.CurrentUser;
import com.example.util.APIState;
import com.example.util.AjaxResult;
import com.example.util.page.Pager;
import com.example.util.page.SeachParamsUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 代码生成 前端控制器
 * </p>
 *
 * @author wangkai
 * @since 2020-10-27
 */
@RestController
@Api(value = "代码生成Controller", tags = {"代码生成操作接口"})
@RequestMapping("/sys/generator")
public class GeneratorController {
    @Autowired
    private IGenTableService genTableServiceImpl;

    @Autowired
    private DbConfig dbConfig;
    @Autowired
    private GenerConfig generConfig;
//    @Autowired
//    private ExampleConfigValue configValue;


    /**
     * 代码生成列表
     *
     * @param pager
     * @return
     */

    @ApiOperation(value = "代码生成列表", httpMethod = "POST")
    @PostMapping(value = "/page")
    public AjaxResult page(@ApiParam(value = "代码生成列表参数", required = true) @RequestBody Pager pager) {
        Page<GenTable> page = new Page<>();
        page.setCurrent(pager.getPageNum());
        page.setSize(pager.getPageSize());
        QueryWrapper<GenTable> queryWrapper = new QueryWrapper<>();
        SeachParamsUtil.loadSearchParam(pager, queryWrapper);
        pager.convertPage(genTableServiceImpl.selectMyPage(page, queryWrapper));
        return new AjaxResult(APIState.S00, pager);
    }


    @ApiOperation(value = "导入列表", httpMethod = "POST")
    @PostMapping(value = "/tablePage")
    public AjaxResult tablePage(@ApiParam(value = "导入列表", required = true) @RequestBody String json) {
        JSONObject jsonObject = JSON.parseObject(json);
        GenTableVo vo = JSON.parseObject(json, GenTableVo.class);
        Page<GenTableVo> page = new Page<>();
        page.setCurrent(jsonObject.getLongValue("pageNum"));
        page.setSize(jsonObject.getLongValue("pageSize"));
        vo.setTableSchema(getTableSchema());
        vo.setNotTableNames(Arrays.asList(generConfig.getNotTablePrefix().split(",")));
        List<GenTableVo> list = genTableServiceImpl.selectTable(vo);
        page.setRecords(list);
        Pager pager = new Pager<>(page);
        return new AjaxResult(APIState.S00, pager);
    }


    /**
     * 代码生成新增
     *
     * @param vos
     * @return
     */
    @ApiOperation(value = "代码生成导入", httpMethod = "POST")
    @PostMapping
    public AjaxResult save(@ApiParam(value = "代码生成导入参数", required = true) @RequestBody List<GenTableVo> vos) {
//        List<GenTableVo> vos = JSON.parseArray(json, GenTableVo.class);
        SysUser sysUser = CurrentUser.getAdminUser();
        vos.forEach(vo -> {
            GenTable genTable = new GenTable();
            genTable.setTableName(vo.getTableName());
            genTable.setTableComment(vo.getTableDescribe());
            String fix = Arrays.asList(generConfig.getTablePrefix().split(",")).stream().filter(info -> vo.getTableName().startsWith(info)).findFirst().get();
            genTable.setClassName(StringUtils.capitalize(StringUtils.underlineToCamel(vo.getTableName().replace(fix, ""))));
            genTable.setPackageName(generConfig.getPackageName());
            genTable.setModuleName(generConfig.getModuleName());
            genTable.setBusinessName(StringUtils.underlineToCamel(vo.getTableName().replace(fix, "")));
            genTable.setCreateTime(new Date());
            genTable.setCreateBy(String.format("%s", sysUser.getId()));
            genTable.insertOrUpdate();
            vo.setTableSchema(getTableSchema());
            List<GenFieldVo> fieldVos = genTableServiceImpl.selectTableColumns(vo);
            fieldVos.forEach(info -> {
                GenTableColumn column = new GenTableColumn();
                column.setTableId(String.format("%s", genTable.getId()));
                column.setColumnName(info.getFieldName());
                column.setColumnComment(info.getFieldComment());
                column.setColumnType(info.getDataType());
                column.setJavaField(StringUtils.underlineToCamel(info.getFieldName()));
                column.setJavaType(getEntityType(info.getDataType()).getType());
                column.setCreateTime(genTable.getCreateTime());
                column.setCreateBy(genTable.getCreateBy());
                column.setIsInsert("1");
                column.setIsEdit("1");
                column.setIsList("1");
                column.setIsQuery("1");
                column.setIsRequired("1");
                column.setHtmlType("input");
                column.insertOrUpdate();
            });
        });
        return new AjaxResult(APIState.S00, "保存成功");
    }


    @ApiOperation(value = "代码生成", httpMethod = "POST")
    @PostMapping("/execute")
    public AjaxResult execute(@ApiParam(value = "代码生成参数", required = true) @RequestBody List<GenTable> vos) throws Exception {
//        List<GenTable> vos = JSON.parseArray(json, GenTable.class);
        if (vos != null && vos.size() > 0) {
            vos.forEach(vo -> {
                GeneratorInfo generatorInfo = new GeneratorInfo();
                generatorInfo.setTableName(vo.getTableName());
                generatorInfo.setPackageName(vo.getPackageName());
                generatorInfo.setModuleName(vo.getModuleName());
                generatorInfo.setBusinessName(vo.getBusinessName());
                Generator generator = Generator.builder(generConfig, dbConfig,vo);
                generator.execute();
            });
//            if (!FileUtil.validateFileDir(configValue.getTemporaryPath())) {
//                FileUtil.mkdir(configValue.getTemporaryPath());
//            }
//            FileOutputStream fos2 = new FileOutputStream(new File(configValue.getTemporaryPath() + "/gen.zip"));
//            FileUtil.toZip(generConfig.getOutTempPath(), fos2, true);
//        FileUtil.deleteFile(generConfig.getOutTempPath());
//            return new AjaxResult(APIState.S00, "生成成功", configValue.getTemporaryPath() + "/gen.zip");
            return new AjaxResult(APIState.S00, "生成成功");
        }
        return new AjaxResult(APIState.S01, "生成失败");
    }

    /**
     * 代码生成编辑
     *
     * @param genTable
     * @return
     */
    @ApiOperation(value = "代码生成编辑", httpMethod = "PUT")
    @PutMapping
    public AjaxResult update(@ApiParam(value = "代码生成编辑参数", required = true) @RequestBody  GenTable genTable) {
//        GenTable genTable = JSON.parseObject(json, GenTable.class);
        if (genTable.insertOrUpdate()) {
            List<GenTableColumn> list = genTable.getColumns();
            list.forEach(info -> info.insertOrUpdate());
            return new AjaxResult(APIState.S00, "保存成功");
        }
        return new AjaxResult(APIState.S01, "保存失败");
    }


    @ApiOperation(value = "代码生成同步", httpMethod = "PUT")
    @GetMapping("/{id}/synchro")
    public AjaxResult synchro(@ApiParam(value = "代码生成同步参数", required = true) @PathVariable Integer id) {
        GenTable genTable = genTableServiceImpl.getMyById(id);
        if (genTable != null) {
            List<GenTableColumn> list = genTable.getColumns();
            list.forEach(info -> info.deleteById());
            GenTableVo vo = new GenTableVo();
            vo.setTableSchema(getTableSchema());
            vo.setTableName(genTable.getTableName());
            List<GenFieldVo> fieldVos = genTableServiceImpl.selectTableColumns(vo);
            fieldVos.forEach(info -> {
                GenTableColumn column = new GenTableColumn();
                column.setTableId(String.format("%s", genTable.getId()));
                column.setColumnName(info.getFieldName());
                column.setColumnComment(info.getFieldComment());
                column.setColumnType(info.getDataType());
                column.setJavaField(StringUtils.underlineToCamel(info.getFieldName()));
                column.setJavaType(getEntityType(info.getDataType()).getType());
                column.setCreateTime(genTable.getCreateTime());
                column.setCreateBy(genTable.getCreateBy());
                column.setIsInsert("1");
                column.setIsEdit("1");
                column.setIsList("1");
                column.setIsQuery("1");
                column.setIsRequired("1");
                column.setHtmlType("input");
                column.insertOrUpdate();
            });
        }
        return new AjaxResult(APIState.S00, "同步成功");
    }


    /**
     * 代码生成刪除
     *
     * @param ids
     * @return
     */
    @ApiOperation(value = "代码生成刪除", httpMethod = "DELETE")
    @DeleteMapping(value = "/{ids}")
    public AjaxResult delete(@ApiParam(value = "代码生成列表参数", required = true) @PathVariable Integer[] ids) {
        if (ids != null) {
            if (genTableServiceImpl.removeByTableIds(Arrays.asList(ids))) {
                return new AjaxResult(APIState.S00, "删除成功");
            }
        }
        return new AjaxResult(APIState.S01, "删除失败");
    }

    private String getTableSchema() {
        String jdbcUrl = dbConfig.getUrl();
        int start = jdbcUrl.lastIndexOf(StringPool.SLASH) + 1;
        int end = jdbcUrl.indexOf(StringPool.QUESTION_MARK);
        return jdbcUrl.substring(start, end);
    }


    private DbColumnType getEntityType(String fieldType) {
        String t = fieldType.toLowerCase();
        if (t.contains("char") || t.contains("text")) {
            return DbColumnType.STRING;
        } else if (t.contains("bigint")) {
            return DbColumnType.LONG;
        } else if (t.contains("tinyint(1)")) {
            return DbColumnType.BOOLEAN;
        } else if (t.contains("int")) {
            return DbColumnType.INTEGER;
        } else if (t.contains("text")) {
            return DbColumnType.STRING;
        } else if (t.contains("bit")) {
            return DbColumnType.BOOLEAN;
        } else if (t.contains("decimal")) {
            return DbColumnType.BIG_DECIMAL;
        } else if (t.contains("clob")) {
            return DbColumnType.CLOB;
        } else if (t.contains("blob")) {
            return DbColumnType.BLOB;
        } else if (t.contains("binary")) {
            return DbColumnType.BYTE_ARRAY;
        } else if (t.contains("float")) {
            return DbColumnType.FLOAT;
        } else if (t.contains("double")) {
            return DbColumnType.DOUBLE;
        } else if (t.contains("json") || t.contains("enum")) {
            return DbColumnType.STRING;
        } else if (t.contains("date") || t.contains("time") || t.contains("year")) {
            return DbColumnType.DATE;
        }
        return DbColumnType.STRING;


    }


}
